package pers.vic.practice.config.thymeleaf;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.AttributeName;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.spring5.context.SpringContextUtils;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressions;
import org.thymeleaf.templatemode.TemplateMode;
import pers.vic.boot.base.exception.CommonException;
import pers.vic.practice.module.system.model.SysDict;
import pers.vic.practice.module.system.service.SysDictService;

import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 描述: 字典select标签处理器  <br/>
 * 		例如 <select vic:dict="xxx" data-value-method="name"  data-value="aa" data-option="请选择"></select>  <br/>
 *
 * @author Vic.xu
 * @date 2022-02-11 9:38
 */
public class DictElementTagProcessor extends AbstractAttributeTagProcessor {

    protected static Logger logger = LoggerFactory.getLogger(DictElementTagProcessor.class);

    public static final String ATTRIBUTE_NAME = "dict";

    static int PRECEDENCE = 1000;

    private static final String SELECT_TAG = "select";


    public DictElementTagProcessor(String dialectPrefix) {
        super(
                // 处理thymeleaf 的模型
                TemplateMode.HTML,
                // 标签前缀名 相当于th:if中的th
                dialectPrefix,
                // No tag name: match any tag name
                null,
                // No prefix to be applied to tag name
                false,
                // 标签前缀的 属性 例如：<kjlink:auth="">
                ATTRIBUTE_NAME,
                // Apply dialect prefix to attribute name
                true,
                // Precedence (inside dialect'.s precedence)
                PRECEDENCE,
                // Remove the matched attribute afterwards
                true);
    }

    @Override
    protected void doProcess(ITemplateContext context, IProcessableElementTag tag, AttributeName attributeName,
                             String attributeValue, IElementTagStructureHandler structureHandler) {
        final IEngineConfiguration configuration = context.getConfiguration();

        /*
         * 获得Thymeleaf标准表达式解析器
         */
        final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);

        /*
         * 将属性值解析为Thymeleaf标准表达式
         */
        final IStandardExpression expression = parser.parseExpression(context, attributeValue);

        // 获得字典表的code
        String code = String.valueOf(expression.execute(context));

        // 获得标签名
        String tagName = tag.getElementCompleteName();

        // 暂时只处理select标签
        if (SELECT_TAG.equalsIgnoreCase(tagName)) {
            try {
                appendSelectOptions(code, context, tag, structureHandler);
            } catch (Exception e) {
                e.printStackTrace();
                throw new CommonException("处理字典select标签出错了：" + e.getMessage());
            }
        }

    }

    private void appendSelectOptions(String code, ITemplateContext context, IProcessableElementTag tag,
                                     IElementTagStructureHandler structureHandler) throws Exception {
        if (StringUtils.isBlank(code)) {
            return;
        }

        SysDictService dictService = getSpringBean(context, SysDictService.class);
        if (dictService == null) {
            logger.warn("无法从spring中获取SysDictService");
            return;
        }
        // 需要选中的值
        String currentValue = tag.getAttributeValue("data-value");

        List<SysDict> list = dictService.findByTypeCode(code);
        list = list.stream().filter(d -> {
            return (d.getEnabled() != null && d.getEnabled() == 1) || StringUtils.equals(d.getValue(), currentValue);
        }).collect(Collectors.toList());
        if (list.size() ==0) {
            return;
        }

        IModelFactory factory = context.getModelFactory();
        IModel model = factory.createModel();

        // 第一个option
        String firstOption = tag.getAttributeValue("data-option");
        if (StringUtils.isNotBlank(firstOption)) {
            addOption(model, factory, firstOption, "", false);
        }

        for (SysDict dict : list) {
            String text = dict.getText();
            String value = dict.getValue();
            addOption(model, factory, text, value,
                    StringUtils.equals(currentValue, value));
        }
        structureHandler.insertImmediatelyAfter(model, true);

    }

    private <T> T getSpringBean(ITemplateContext context, Class<T> clazz) {
        ApplicationContext applicationContext = SpringContextUtils.getApplicationContext(context);
        return applicationContext.getBean(clazz);

    }

    private void addOption(IModel model, IModelFactory factory, String name, String value, boolean selected) {
        String open = "option value=\"" + value + "\"";
        if (selected) {
            open += " selected=\"selected\"";
        }
        model.add(factory.createOpenElementTag(open));
        model.add(factory.createText(name));
        model.add(factory.createCloseElementTag("option"));
    }

    public static void main(String[] args) {
        Integer a = null;
        System.out.println(1==a);
    }

}
